package org.zjx.util;

import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.RECT;
import com.sun.jna.ptr.IntByReference;
import org.zjx.entity.Rect;

import java.util.ArrayList;
import java.util.List;

public class HwndUtil {

    // 缓冲区大小常量
    private static final int MAX_CLASS_NAME_LENGTH = 256;
    private static final int MAX_TITLE_LENGTH = 1024;

    /**
     * 获取窗口类名
     * @param hwnd 窗口句柄
     * @return 窗口类名，如果获取失败返回null
     */
    public static String getWindowClassName(HWND hwnd) {
        if (hwnd == null) {
            return null;
        }

        char[] buffer = new char[MAX_CLASS_NAME_LENGTH];
        int length = User32.INSTANCE.GetClassName(hwnd, buffer, buffer.length);
        if (length > 0) {
            return new String(buffer, 0, length);
        }
        return null;
    }

    /**
     * 获取窗口标题
     * @param hwnd 窗口句柄
     * @return 窗口标题，如果获取失败返回null
     */
    public static String getWindowTitle(HWND hwnd) {
        if (hwnd == null) {
            return null;
        }

        char[] buffer = new char[MAX_TITLE_LENGTH];
        int length = User32.INSTANCE.GetWindowText(hwnd, buffer, buffer.length);
        if (length > 0) {
            return new String(buffer, 0, length);
        }
        return null;
    }

    /**
     * 获取窗口的进程ID
     * @param hwnd 窗口句柄
     * @return 进程ID，如果获取失败返回0
     */
    public static int getWindowProcessId(HWND hwnd) {
        if (hwnd == null) {
            return 0;
        }

        IntByReference processId = new IntByReference();
        User32.INSTANCE.GetWindowThreadProcessId(hwnd, processId);
        return processId.getValue();
    }

    /**
     * 获取所有顶层窗口的句柄
     * @return 窗口句柄列表
     */
    public static List<HWND> getAllTopWindows() {
        List<HWND> windows = new ArrayList<>();
        User32.INSTANCE.EnumWindows((hwnd, data) -> {
            windows.add(hwnd);
            return true;
        }, null);
        return windows;
    }

    /**
     * 获取窗口及其信息（类名和标题）
     * @param hwnd 窗口句柄
     * @return 包含窗口信息的字符串
     */
    public static String getWindowInfo(HWND hwnd) {
        String className = getWindowClassName(hwnd);
        String title = getWindowTitle(hwnd);
        int pid = getWindowProcessId(hwnd);

        return String.format("HWND: 0x%X, Class: %s, Title: %s, PID: %d",
                hwnd != null ? hwnd.hashCode() : 0,
                className,
                title,
                pid);
    }


    public static List<HWND> getHwndS(String className, String titleName) {
        List<HWND> hs = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            HWND before = null;
            if (!hs.isEmpty()) before = hs.get(hs.size() - 1);
            HWND hwnd1 = User32.INSTANCE.FindWindowEx(null, before, className, titleName);
            if (hwnd1 != null) {
                hs.add(hwnd1);
            }
        }
        return hs;
    }

    public static boolean haveHwnd(HWND hwnd) {
        return User32.INSTANCE.IsWindowVisible(hwnd);
    }

    public static HWND getHwnd(String className, String titleName) {
        List<HWND> hs = getHwndS(className, titleName);
        if (!hs.isEmpty()) return hs.get(0);
        return null;
    }

    public static Rect getWindowRect(HWND hwnd) {
        if (hwnd == null) throw new NullPointerException("hwnd is null");
        RECT rect = new RECT();
        User32.INSTANCE.GetWindowRect(hwnd, rect);
        return new Rect(rect.left, rect.top, rect.right, rect.bottom);
    }

    public static void preposition(HWND hwnd) {
        if (hwnd == null) throw new NullPointerException("hwnd is null");
        User32.INSTANCE.SetForegroundWindow(hwnd);
    }

    public static void moveWindow(HWND hwnd, int x, int y) {
        if (hwnd == null) throw new NullPointerException("hwnd is null");
        User32.INSTANCE.ShowWindow(hwnd, 9); // Restore the window (SW_RESTORE)
        preposition(hwnd);
        Rect rect = getWindowRect(hwnd);
        User32.INSTANCE.MoveWindow(hwnd, x, y, rect.getWidth() - 1, rect.getHeight() - 1, true);
    }

}
